<?php
//
//  VictoryCMS - Content managment system and framework.
//  Copyright (C) 2009  Lewis Gunsch
//
//  This file is part of VictoryCMS.
//  
//  VictoryCMS is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  VictoryCMS is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//  
//  You should have received a copy of the GNU General Public License
//  along with VictoryCMS.  If not, see <http://www.gnu.org/licenses/>.

/**
 * VictoryCMS - PageFactory
 * 
 * @license http://www.gnu.org/licenses/gpl.html
 * @author Lewis Gunsch
 * @filesource
 * @package DisplayablePages
 */

/**
 * Creates instances of DisplayablePage. This is a class 
 * uses the Factory design pattern to create instances of 
 * Displayable Page used by the page displayer object.
 * 
 * @package DisplayablePages
 * 
 * @todo Available pages should be read from an xml file
 * @todo create custome exceptions for this class.
 * @todo Maybe factory should look everywhere for DisplayablePages?
 */
class PageFactory {
	
	/**
	 * Creates a new DisplayablePage of $name subtype or null
	 * if $name does not match any known subtype class.
	 * 
	 * @param String The DisplayablePage class to create
	 * 
	 * @return DisplayablePage The created page object.
	 * 
	 * @todo create custome exception here
	 */
	public static function createDisplayablePage($name) {
	
		$success = loadFromFolder($name, FolderMap::getPageFolder());
		
		// if debugging is enabled then try to load from test folder
		// which should be under the displayable_pages folder
		if ($success == false && VarMap::get(VarMapKeys::debug_enabled) == true) {
			$success = loadFromFolder($name, FolderMap::getTestingPageFolder());
		}
		if ($success == true) {
			$classInst = new $name;
		} else {
			throw new NotFoundException($name);
		}
		if (!$classInst instanceof DisplayablePage) {
			throw new DataTypeException('DisplayablePage', $name);
		}
		return $classInst;
	}
	
	/**
	 * Checks whether a string $page is the name of a DisplayablePage or not.
	 * 
	 * @returns boolean True if the page is a DisplayablePage, false if not.
	 */
	public static function checkIfDisplayablePage($page) {
		try {
			PageFactory::createDisplayablePage($page);
		} catch(Exception $ex) {
			return false;
		}
		return true;
	}
	
	/**
	 * This returns an array of class name strings that are instances 
	 * of DisplayablePage.
	 * 
	 * @return arrray Array of DisplayablePages available.
	 */
	public static function listDisplayablePages() {
		$pages = array();

		// open this directory
		$path = FolderMap::getPageFolder();
		self::loadDisplayablePagesFromFolder($pages, $path);
		
		// list testing pages if necessary
		if (VarMap::get(VarMapKeys::debug_enabled) == true) {
			$path = FolderMap::getTestingPageFolder();
			self::loadDisplayablePagesFromFolder($pages, $path);
		}
		
		return $pages;
	}
	
	/**
	 * Loads any displayable pages from the folder $folderPath and adds them
	 * into the $pages array. This will not add any subdirectories, nor any 
	 * hidden pages. The $pages array should be instantiated beforehand.
	 * 
	 * @param $pages The array of pages to append to.
	 * @param $folderPath The path to the folder to load the pages from.
	 * @return void
	 */
	private static function loadDisplayablePagesFromFolder(array &$pages, $folderPath) {
		$pagesDir = opendir($folderPath);
		
		// get each page file name
		while($entryName = readdir($pagesDir)) {
			// don't load hidden files or items that are not DisplayablePages
			// such as directories
			if (is_dir($entryName) == false && substr("$entryName", 0, 1) != ".") { 
				$pageClass = preg_replace('/\.[^.]*$/', '', $entryName);
				if (self::checkIfDisplayablePage($pageClass) == true) {
					$pages[] = $pageClass;
				}
			}
		}
		
		sort($pages);
		closedir($pagesDir);
	}
}
?>
